using Godot;
using PaintAWorld.ChunkUpdates;
using PaintAWorld.PlayerInputs;

namespace PaintAWorld.Gd
{
    public partial class Level : Node
	{

		[Export]
		public PlayerNode player;

		[Export]
		public VoxelModelInstance chunk;

		private Client _client;
		private bool _handleInputs;

		public IWorld World { get; private set; }

		public void Setup(Client client, IWorld world)
		{
			_client = client;
			World = world;
			_client.UpdateHUD();
		}

		public override void _Ready()
		{
			player.level = this;
		}

		public override void _Process(double delta)
		{
			ProcessPlayerInput();

			while (World.PollEvent(out var gameEvent))
			{
				switch (gameEvent)
				{
					case WorldChunkUpdateEvent tue:
						switch (tue.content)
						{
							case TerrainUpdate terrain:
								chunk.Regen(terrain.newModel, Vector3.Zero, 1.0f);
								break;
						}
						break;
				}
			}
		}

		private void ProcessPlayerInput()
		{
			if (!_handleInputs) return;

			if (Input.IsActionJustPressed("primary"))
			{
				if (player.Primary() is var ctx)
				{
					World.DispatchInput(new(ctx));
				}
			}

			if (Input.IsActionJustPressed("secondary"))
			{
				if (player.Secondary() is var ctx)
				{
					World.DispatchInput(new(ctx));
				}
			}

			var movement = Input.GetVector("move_left", "move_right", "move_forward", "move_back");
			var vertical = Input.GetAxis("sneak", "jump");
			player.Move(movement, vertical);
			World.DispatchInput(new(new Move(player.Position)));

			_client.debug.Text = $"Position: {player.Position}, Look: {player.EyeRotation}, Index: {player.CurrentIndex}";
		}

		public override void _Input(InputEvent e)
		{
			if (!_handleInputs) return;

			if (e is InputEventMouseMotion mme)
			{
				player.Look(0.01f * mme.Relative);
				_client.dir.GlobalBasis = player.eye.GlobalBasis.Inverse();
			}

			if (e is InputEventMouseButton mbe)
			{
				if (mbe.Pressed)
				{
					if (mbe.ButtonIndex == MouseButton.WheelUp)
					{
						player.MoveBackShortcut();
						_client.UpdateHUD();
					}

					if (mbe.ButtonIndex == MouseButton.WheelDown)
					{
						player.MoveNextShortcut();
						_client.UpdateHUD();
					}
				}
			}
		}

		public void EnableInput()
		{
			_handleInputs = true;
		}

		public void DisableInput()
		{
			_handleInputs = false;
		}

		public bool InputDisabled() => _handleInputs == false;

		public void RunCommand(string cmd) => World.RunCommand(cmd);
	}
}